Shiny App Experiment Lab

Libraries

library(here)
library(dplyr)
library(arrow)

Reading data

census_dataset |> collect()

Reading specific data

pueb_norm <- census_dataset |>
    filter(NOM_ENT=="Puebla") |> 
    collect()
Warning: Invalid metadata$rWarning: Invalid metadata$rWarning: Invalid metadata$rWarning: Invalid metadata$r
pueb_norm
unique(pueb_norm$NOM_MUN)
  [1] "Total de la entidad Puebla"       "Acajete"                          "Acateno"                          "Acatlán"                         
  [5] "Acatzingo"                        "Acteopan"                         "Ahuacatlán"                       "Ahuatlán"                        
  [9] "Ahuazotepec"                      "Ahuehuetitla"                     "Ajalpan"                          "Albino Zertuche"                 
 [13] "Aljojuca"                         "Altepexi"                         "Amixtlán"                         "Amozoc"                          
 [17] "Aquixtla"                         "Atempan"                          "Atexcal"                          "Atlixco"                         
 [21] "Atoyatempan"                      "Atzala"                           "Atzitzihuacán"                    "Atzitzintla"                     
 [25] "Axutla"                           "Ayotoxco de Guerrero"             "Calpan"                           "Caltepec"                        
 [29] "Camocuautla"                      "Caxhuacan"                        "Coatepec"                         "Coatzingo"                       
 [33] "Cohetzala"                        "Cohuecan"                         "Coronango"                        "Coxcatlán"                       
 [37] "Coyomeapan"                       "Coyotepec"                        "Cuapiaxtla de Madero"             "Cuautempan"                      
 [41] "Cuautinchán"                      "Cuautlancingo"                    "Cuayuca de Andrade"               "Cuetzalan del Progreso"          
 [45] "Cuyoaco"                          "Chalchicomula de Sesma"           "Chapulco"                         "Chiautla"                        
 [49] "Chiautzingo"                      "Chiconcuautla"                    "Chichiquila"                      "Chietla"                         
 [53] "Chigmecatitlán"                   "Chignahuapan"                     "Chignautla"                       "Chila"                           
 [57] "Chila de la Sal"                  "Honey"                            "Chilchotla"                       "Chinantla"                       
 [61] "Domingo Arenas"                   "Eloxochitlán"                     "Epatlán"                          "Esperanza"                       
 [65] "Francisco Z. Mena"                "General Felipe Ángeles"           "Guadalupe"                        "Guadalupe Victoria"              
 [69] "Hermenegildo Galeana"             "Huaquechula"                      "Huatlatlauca"                     "Huauchinango"                    
 [73] "Huehuetla"                        "Huehuetlán el Chico"              "Huejotzingo"                      "Hueyapan"                        
 [77] "Hueytamalco"                      "Hueytlalpan"                      "Huitzilan de Serdán"              "Huitziltepec"                    
 [81] "Atlequizayan"                     "Ixcamilpa de Guerrero"            "Ixcaquixtla"                      "Ixtacamaxtitlán"                 
 [85] "Ixtepec"                          "Izúcar de Matamoros"              "Jalpan"                           "Jolalpan"                        
 [89] "Jonotla"                          "Jopala"                           "Juan C. Bonilla"                  "Juan Galindo"                    
 [93] "Juan N. Méndez"                   "Lafragua"                         "Libres"                           "La Magdalena Tlatlauquitepec"    
 [97] "Mazapiltepec de Juárez"           "Mixtla"                           "Molcaxac"                         "Cañada Morelos"                  
[101] "Naupan"                           "Nauzontla"                        "Nealtican"                        "Nicolás Bravo"                   
[105] "Nopalucan"                        "Ocotepec"                         "Ocoyucan"                         "Olintla"                         
[109] "Oriental"                         "Pahuatlán"                        "Palmar de Bravo"                  "Pantepec"                        
[113] "Petlalcingo"                      "Piaxtla"                          "Puebla"                           "Quecholac"                       
[117] "Quimixtlán"                       "Rafael Lara Grajales"             "Los Reyes de Juárez"              "San Andrés Cholula"              
[121] "San Antonio Cañada"               "San Diego la Mesa Tochimiltzingo" "San Felipe Teotlalcingo"          "San Felipe Tepatlán"             
[125] "San Gabriel Chilac"               "San Gregorio Atzompa"             "San Jerónimo Tecuanipan"          "San Jerónimo Xayacatlán"         
[129] "San José Chiapa"                  "San José Miahuatlán"              "San Juan Atenco"                  "San Juan Atzompa"                
[133] "San Martín Texmelucan"            "San Martín Totoltepec"            "San Matías Tlalancaleca"          "San Miguel Ixitlán"              
[137] "San Miguel Xoxtla"                "San Nicolás Buenos Aires"         "San Nicolás de los Ranchos"       "San Pablo Anicano"               
[141] "San Pedro Cholula"                "San Pedro Yeloixtlahuaca"         "San Salvador el Seco"             "San Salvador el Verde"           
[145] "San Salvador Huixcolotla"         "San Sebastián Tlacotepec"         "Santa Catarina Tlaltempan"        "Santa Inés Ahuatempan"           
[149] "Santa Isabel Cholula"             "Santiago Miahuatlán"              "Huehuetlán el Grande"             "Santo Tomás Hueyotlipan"         
[153] "Soltepec"                         "Tecali de Herrera"                "Tecamachalco"                     "Tecomatlán"                      
[157] "Tehuacán"                         "Tehuitzingo"                      "Tenampulco"                       "Teopantlán"                      
[161] "Teotlalco"                        "Tepanco de López"                 "Tepango de Rodríguez"             "Tepatlaxco de Hidalgo"           
[165] "Tepeaca"                          "Tepemaxalco"                      "Tepeojuma"                        "Tepetzintla"                     
[169] "Tepexco"                          "Tepexi de Rodríguez"              "Tepeyahualco"                     "Tepeyahualco de Cuauhtémoc"      
[173] "Tetela de Ocampo"                 "Teteles de Avila Castillo"        "Teziutlán"                        "Tianguismanalco"                 
[177] "Tilapa"                           "Tlacotepec de Benito Juárez"      "Tlacuilotepec"                    "Tlachichuca"                     
[181] "Tlahuapan"                        "Tlaltenango"                      "Tlanepantla"                      "Tlaola"                          
[185] "Tlapacoya"                        "Tlapanalá"                        "Tlatlauquitepec"                  "Tlaxco"                          
[189] "Tochimilco"                       "Tochtepec"                        "Totoltepec de Guerrero"           "Tulcingo"                        
[193] "Tuzamapan de Galeana"             "Tzicatlacoyan"                    "Venustiano Carranza"              "Vicente Guerrero"                
[197] "Xayacatlán de Bravo"              "Xicotepec"                        "Xicotlán"                         "Xiutetelco"                      
[201] "Xochiapulco"                      "Xochiltepec"                      "Xochitlán de Vicente Suárez"      "Xochitlán Todos Santos"          
[205] "Yaonáhuac"                        "Yehualtepec"                      "Zacapala"                         "Zacapoaxtla"                     
[209] "Zacatlán"                         "Zapotitlán"                       "Zapotitlán de Méndez"             "Zaragoza"                        
[213] "Zautla"                           "Zihuateutla"                      "Zinacatepec"                      "Zongozotla"                      
[217] "Zoquiapan"                        "Zoquitlán"                       

Example

extract_coordinates <- function(data, municipality, locality) {
  selected_location <- data |> 
    filter(NOM_MUN == municipality, NOM_LOC == locality)
  
  coordinates <- tibble(
    long = selected_location$longitude_decimal,
    lat = selected_location$latitude_decimal
  )
  
  return(coordinates)
}


municipality <- "Acajete"
locality <- "Santa Isabel Tepetzala"

red_point <- extract_coordinates(pueb_norm, municipality, locality) |> 
  slice(1)

# red_point <- data.frame(long = -98.2035, lat = 19.0414)

filtered_geojson <- geojson_file |> 
  filter(name == "Puebla")
Error: object 'geojson_file' not found

Population graph

Getting column names

column_names <- names(pueb_norm)
column_names
  [1] "ENTIDAD"           "MUN"               "NOM_MUN"           "LOC"               "NOM_LOC"           "LONGITUD"          "LATITUD"          
  [8] "ALTITUD"           "POBTOT"            "POBFEM"            "POBMAS"            "REL_H_M"           "POB0_14"           "POB15_64"         
 [15] "POB65_MAS"         "P_0A4"             "P_0A4_F"           "P_0A4_M"           "P_5A9"             "P_5A9_F"           "P_5A9_M"          
 [22] "P_10A14"           "P_10A14_F"         "P_10A14_M"         "P_15A19"           "P_15A19_F"         "P_15A19_M"         "P_20A24"          
 [29] "P_20A24_F"         "P_20A24_M"         "P_25A29"           "P_25A29_F"         "P_25A29_M"         "P_30A34"           "P_30A34_F"        
 [36] "P_30A34_M"         "P_35A39"           "P_35A39_F"         "P_35A39_M"         "P_40A44"           "P_40A44_F"         "P_40A44_M"        
 [43] "P_45A49"           "P_45A49_F"         "P_45A49_M"         "P_50A54"           "P_50A54_F"         "P_50A54_M"         "P_55A59"          
 [50] "P_55A59_F"         "P_55A59_M"         "P_60A64"           "P_60A64_F"         "P_60A64_M"         "P_65A69"           "P_65A69_F"        
 [57] "P_65A69_M"         "P_70A74"           "P_70A74_F"         "P_70A74_M"         "P_75A79"           "P_75A79_F"         "P_75A79_M"        
 [64] "P_80A84"           "P_80A84_F"         "P_80A84_M"         "P_85YMAS"          "P_85YMAS_F"        "P_85YMAS_M"        "PROM_HNV"         
 [71] "PNACENT"           "PNACENT_F"         "PNACENT_M"         "PNACOE"            "PNACOE_F"          "PNACOE_M"          "PRES2015"         
 [78] "PRES2015_F"        "PRES2015_M"        "PRESOE15"          "PRESOE15_F"        "PRESOE15_M"        "P3YM_HLI"          "P3YM_HLI_F"       
 [85] "P3YM_HLI_M"        "P3HLINHE"          "P3HLINHE_F"        "P3HLINHE_M"        "P3HLI_HE"          "P3HLI_HE_F"        "P3HLI_HE_M"       
 [92] "PHOG_IND"          "POB_AFRO"          "POB_AFRO_F"        "POB_AFRO_M"        "PCON_DISC"         "PCON_LIMI"         "PSIND_LIM"        
 [99] "P3A5_NOA"          "P3A5_NOA_F"        "P3A5_NOA_M"        "P6A11_NOA"         "P6A11_NOAF"        "P6A11_NOAM"        "P12A14NOA"        
[106] "P12A14NOAF"        "P12A14NOAM"        "P15A17A"           "P15A17A_F"         "P15A17A_M"         "P18A24A"           "P18A24A_F"        
[113] "P18A24A_M"         "P8A14AN"           "P8A14AN_F"         "P8A14AN_M"         "P15YM_AN"          "P15YM_AN_F"        "P15YM_AN_M"       
[120] "P15YM_SE"          "P15YM_SE_F"        "P15YM_SE_M"        "P15PRI_IN"         "P15PRI_INF"        "P15PRI_INM"        "P15PRI_CO"        
[127] "P15PRI_COF"        "P15PRI_COM"        "P15SEC_IN"         "P15SEC_INF"        "P15SEC_INM"        "P15SEC_CO"         "P15SEC_COF"       
[134] "P15SEC_COM"        "P18YM_PB"          "P18YM_PB_F"        "P18YM_PB_M"        "GRAPROES"          "GRAPROES_F"        "GRAPROES_M"       
[141] "PEA"               "PEA_F"             "PEA_M"             "PE_INAC"           "PE_INAC_F"         "PE_INAC_M"         "POCUPADA"         
[148] "POCUPADA_F"        "POCUPADA_M"        "PDESOCUP"          "PDESOCUP_F"        "PDESOCUP_M"        "PSINDER"           "PDER_SS"          
[155] "P12YM_SOLT"        "P12YM_CASA"        "P12YM_SEPA"        "PCATOLICA"         "PRO_CRIEVA"        "POTRAS_REL"        "PSIN_RELIG"       
[162] "TOTHOG"            "HOGJEF_F"          "HOGJEF_M"          "POBHOG"            "PHOGJEF_F"         "PHOGJEF_M"         "longitude_decimal"
[169] "latitude_decimal"  "NOM_ENT"          

Getting column names that have to do with population age cohorts (Masculine/Feminine)

matching_columns <- grep("^P_.*[MF]$", column_names, value = TRUE)
matching_columns
 [1] "P_0A4_F"    "P_0A4_M"    "P_5A9_F"    "P_5A9_M"    "P_10A14_F"  "P_10A14_M"  "P_15A19_F"  "P_15A19_M"  "P_20A24_F"  "P_20A24_M"  "P_25A29_F" 
[12] "P_25A29_M"  "P_30A34_F"  "P_30A34_M"  "P_35A39_F"  "P_35A39_M"  "P_40A44_F"  "P_40A44_M"  "P_45A49_F"  "P_45A49_M"  "P_50A54_F"  "P_50A54_M" 
[23] "P_55A59_F"  "P_55A59_M"  "P_60A64_F"  "P_60A64_M"  "P_65A69_F"  "P_65A69_M"  "P_70A74_F"  "P_70A74_M"  "P_75A79_F"  "P_75A79_M"  "P_80A84_F" 
[34] "P_80A84_M"  "P_85YMAS_F" "P_85YMAS_M"

Separate by sex

ending_in_M <- character(0)
ending_in_F <- character(0)

# Iterate over the matching column names and separate into M or F vectors
for (col_name in matching_columns) {
  if (endsWith(col_name, "M")) {
    ending_in_M <- c(ending_in_M, col_name)
  } else if (endsWith(col_name, "F")) {
    ending_in_F <- c(ending_in_F, col_name)
  }
}

# Print the vectors
print("Column names ending in M:")
[1] "Column names ending in M:"
print(ending_in_M)
 [1] "P_0A4_M"    "P_5A9_M"    "P_10A14_M"  "P_15A19_M"  "P_20A24_M"  "P_25A29_M"  "P_30A34_M"  "P_35A39_M"  "P_40A44_M"  "P_45A49_M"  "P_50A54_M" 
[12] "P_55A59_M"  "P_60A64_M"  "P_65A69_M"  "P_70A74_M"  "P_75A79_M"  "P_80A84_M"  "P_85YMAS_M"
print("Column names ending in F:")
[1] "Column names ending in F:"
print(ending_in_F)
 [1] "P_0A4_F"    "P_5A9_F"    "P_10A14_F"  "P_15A19_F"  "P_20A24_F"  "P_25A29_F"  "P_30A34_F"  "P_35A39_F"  "P_40A44_F"  "P_45A49_F"  "P_50A54_F" 
[12] "P_55A59_F"  "P_60A64_F"  "P_65A69_F"  "P_70A74_F"  "P_75A79_F"  "P_80A84_F"  "P_85YMAS_F"
library(ggplot2)
library(dplyr)

cohort_names_m <- c("P_0A4_M",
                    "P_5A9_M",
                    "P_10A14_M",
                    "P_15A19_M",
                    "P_20A24_M",
                    "P_25A29_M",
                    "P_30A34_M",
                    "P_35A39_M",
                    "P_40A44_M",
                    "P_45A49_M",
                    "P_50A54_M",
                    "P_55A59_M",
                    "P_60A64_M",
                    "P_65A69_M",
                    "P_70A74_M",
                    "P_75A79_M",
                    "P_80A84_M",
                    "P_85YMAS_M")

cohort_names_f <- c("P_0A4_F",
                    "P_5A9_F",
                    "P_10A14_F",
                    "P_15A19_F",
                    "P_20A24_F",
                    "P_25A29_F",
                    "P_30A34_F",
                    "P_35A39_F",
                    "P_40A44_F",
                    "P_45A49_F",
                    "P_50A54_F",
                    "P_55A59_F",
                    "P_60A64_F",
                    "P_65A69_F", 
                    "P_70A74_F",
                    "P_75A79_F",
                    "P_80A84_F", 
                    "P_85YMAS_F")



municipality <- "Acajete"
locality <- "San Javier"

pueb_norm_filt <- pueb_norm |> 
    filter(NOM_MUN == municipality, NOM_LOC == locality)

cohort_counts_m <- as.numeric(pueb_norm_filt[1,cohort_names_m])
cohort_counts_f <- as.numeric(pueb_norm_filt[1,cohort_names_f])

data <- tibble(
  Cohort = c(cohort_names_m, cohort_names_f),
  Count = c(cohort_counts_m, cohort_counts_f),
  Sex = rep(c("Male", "Female"), each = length(cohort_names_m))
)

# Plotting population pyramid
ggplot(data, aes(x = reorder(Cohort, -Count), y = Count, fill = Sex)) +
  geom_bar(stat = "identity", position = "identity") +
  scale_fill_manual(values = c("blue", "pink")) +  
  coord_flip() +  
  labs(title = "Population Pyramid",
       x = "Population Count",
       y = "Age Cohort",
       fill = "Sex") +
  theme_minimal()  

new_ages <- c("0-4",
                 "5-9",
                 "10-14",
                 "15-19",
                 "20-24",
                 "25-29", 
                 "30-34", 
                 "35-39", 
                 "40-44", 
                 "45-49",
                 "50-54",
                 "55-59",
                 "60-64", 
                 "65-69",
                 "70-74", 
                 "75-79", 
                 "80-84", 
                 "85+")

data <- tibble(
  Age = paste0(new_ages),
  Male = sample(200:1000, length(cohort_names_m), replace = TRUE),
  Female = sample(200:1000, length(cohort_names_f), replace = TRUE)
)

data_long <- pivot_longer(
  data, 
  cols = c(Male, Female), 
  names_to = "Sex", 
  values_to = "Population"
)

basic_plot <- ggplot(data_long, aes(x = Age, y = ifelse(Sex == "Male", -Population, Population), fill = Sex)) +
  geom_bar(stat = "identity") +
  scale_y_continuous(labels = abs, limits = max(data_long$Population) * c(-1, 1)) +
  coord_flip() +
  theme_minimal() +
  labs(x = "Age", y = "Population", fill = "Sex", title = "Population Pyramid")

basic_plot

Complete pipeline

census_dataset <- open_dataset(here("data", "processed", "parquet_data_coords"))


pueb_norm <- census_dataset |>
    filter(NOM_ENT=="Puebla") |> 
    collect()
Warning: Invalid metadata$rWarning: Invalid metadata$rWarning: Invalid metadata$rWarning: Invalid metadata$r
municipality <- "Acajete"
locality <- "San Javier"

pueb_norm_filt <- pueb_norm |> 
    filter(NOM_MUN == municipality, NOM_LOC == locality)


cohort_names_m <- c("P_0A4_M",
                    "P_5A9_M",
                    "P_10A14_M",
                    "P_15A19_M",
                    "P_20A24_M",
                    "P_25A29_M",
                    "P_30A34_M",
                    "P_35A39_M",
                    "P_40A44_M",
                    "P_45A49_M",
                    "P_50A54_M",
                    "P_55A59_M",
                    "P_60A64_M",
                    "P_65A69_M",
                    "P_70A74_M",
                    "P_75A79_M",
                    "P_80A84_M",
                    "P_85YMAS_M")

cohort_names_f <- c("P_0A4_F",
                    "P_5A9_F",
                    "P_10A14_F",
                    "P_15A19_F",
                    "P_20A24_F",
                    "P_25A29_F",
                    "P_30A34_F",
                    "P_35A39_F",
                    "P_40A44_F",
                    "P_45A49_F",
                    "P_50A54_F",
                    "P_55A59_F",
                    "P_60A64_F",
                    "P_65A69_F", 
                    "P_70A74_F",
                    "P_75A79_F",
                    "P_80A84_F", 
                    "P_85YMAS_F")



new_ages <- c("0-4",
                 "5-9",
                 "10-14",
                 "15-19",
                 "20-24",
                 "25-29", 
                 "30-34", 
                 "35-39", 
                 "40-44", 
                 "45-49",
                 "50-54",
                 "55-59",
                 "60-64", 
                 "65-69",
                 "70-74", 
                 "75-79", 
                 "80-84", 
                 "85+")


data <- tibble(
  Age = paste0(new_ages),
  Male = as.numeric(pueb_norm_filt[1,cohort_names_m]),
  Female = as.numeric(pueb_norm_filt[1,cohort_names_f])
)

data_long <- pivot_longer(
  data, 
  cols = c(Male, Female), 
  names_to = "Sex", 
  values_to = "Population"
)
basic_plot <- ggplot(data_long, aes(x = Age, y = ifelse(Sex == "Male", -Population, Population), fill = Sex)) +
  geom_bar(stat = "identity") +
  scale_y_continuous(labels = abs, limits = max(data_long$Population) * c(-1, 1)) +
  coord_flip() +
  theme_minimal() +
  labs(x = "Age", y = "Population", fill = "Sex", title = "Population Pyramid")

basic_plot

Card

# card <- census_dataset |>  
#     filter(
#       NOM_ENT == "Puebla",
#       NOM_MUN == "Acateno",
#       NOM_LOC == "Santa Andrea"
#     ) |> 
#   collect()
    
    total_population <- as.numeric(card[1, c("POBTOT")], na.rm = TRUE)
    paste("Total Population:", total_population)
[1] "Total Population: 1"

Pie

tot <- census_dataset |>
    filter(NOM_ENT=="Total nacional") |> 
    collect()
Warning: Invalid metadata$rWarning: Invalid metadata$rWarning: Invalid metadata$rWarning: Invalid metadata$r
tot
# origin <- census_dataset |>  
#      filter(
#       NOM_ENT == "Puebla",
#       NOM_MUN == "Acateno",
#       NOM_LOC == "Santa Andrea"
#     ) |>
#   collect()
    
tot
    
    # Extract birth data
    birth_local <- as.numeric(tot[1, "PNACENT"])
    birth_another <- as.numeric(tot[1, "PNACOE"])
    
    # Debugging output
    print(paste("Birth Local:", birth_local))
[1] "Birth Local: 102724322"
    print(paste("Birth Another:", birth_another))
[1] "Birth Another: 21611963"
    
    # Create ratio dataframe
    ratio_df <- tibble(
      Category = c("Local", "Other"),
      Ratio = c(birth_local, birth_another)
    )
    
    # Calculate percentages
    ratio_df$Percentage <- ratio_df$Ratio / sum(ratio_df$Ratio) * 100
    
    # Plot the pie chart
    gg <- ggplot(ratio_df, aes(x = "", y = Ratio, fill = Category)) +
      geom_bar(stat = "identity", width = 1) +
      coord_polar(theta = "y") +
      theme_void() +
      theme(legend.position = "bottom") +
      scale_fill_manual(values = c("#00BFC4", "#F8766D")) +
      geom_text(aes(label = paste0(round(Percentage), "%")), 
                position = position_stack(vjust = 0.5),
                size = 5, color = "white", fontface = "bold")
    
    gg

NA
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCmF1dGhvcjogTWFyY28gUG9sbyBCcmF2byBNb250aWVsDQpkYXRlOiAyMDIwLTA0LTIzDQotLS0NCg0KIyBTaGlueSBBcHAgRXhwZXJpbWVudCBMYWINCg0KIyMjIExpYnJhcmllcw0KDQpgYGB7cn0NCmxpYnJhcnkoaGVyZSkNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGFycm93KQ0KYGBgDQoNCiMjIyBSZWFkaW5nIGRhdGENCg0KYGBge3J9DQpjZW5zdXNfZGF0YXNldCA8LSBvcGVuX2RhdGFzZXQoaGVyZSgiZGF0YSIsICJwcm9jZXNzZWQiLCAicGFycXVldF9kYXRhX2Nvb3JkcyIpKQ0KY2Vuc3VzX2RhdGFzZXQNCg0KYGBgDQoNCiMjIyBSZWFkaW5nIHNwZWNpZmljIGRhdGENCg0KYGBge3J9DQpwdWViX25vcm0gPC0gY2Vuc3VzX2RhdGFzZXQgfD4NCiAgICBmaWx0ZXIoTk9NX0VOVD09IlB1ZWJsYSIpIHw+IA0KICAgIGNvbGxlY3QoKQ0KDQpwdWViX25vcm0NCmBgYA0KDQpgYGB7cn0NCnVuaXF1ZShwdWViX25vcm0kTk9NX01VTikNCmBgYA0KDQojIyMgRXhhbXBsZQ0KDQpgYGB7cn0NCmV4dHJhY3RfY29vcmRpbmF0ZXMgPC0gZnVuY3Rpb24oZGF0YSwgbXVuaWNpcGFsaXR5LCBsb2NhbGl0eSkgew0KICBzZWxlY3RlZF9sb2NhdGlvbiA8LSBkYXRhIHw+IA0KICAgIGZpbHRlcihOT01fTVVOID09IG11bmljaXBhbGl0eSwgTk9NX0xPQyA9PSBsb2NhbGl0eSkNCiAgDQogIGNvb3JkaW5hdGVzIDwtIHRpYmJsZSgNCiAgICBsb25nID0gc2VsZWN0ZWRfbG9jYXRpb24kbG9uZ2l0dWRlX2RlY2ltYWwsDQogICAgbGF0ID0gc2VsZWN0ZWRfbG9jYXRpb24kbGF0aXR1ZGVfZGVjaW1hbA0KICApDQogIA0KICByZXR1cm4oY29vcmRpbmF0ZXMpDQp9DQoNCg0KbXVuaWNpcGFsaXR5IDwtICJBY2FqZXRlIg0KbG9jYWxpdHkgPC0gIlNhbnRhIElzYWJlbCBUZXBldHphbGEiDQoNCnJlZF9wb2ludCA8LSBleHRyYWN0X2Nvb3JkaW5hdGVzKHB1ZWJfbm9ybSwgbXVuaWNpcGFsaXR5LCBsb2NhbGl0eSkgfD4gDQogIHNsaWNlKDEpDQoNCiMgcmVkX3BvaW50IDwtIGRhdGEuZnJhbWUobG9uZyA9IC05OC4yMDM1LCBsYXQgPSAxOS4wNDE0KQ0KDQpmaWx0ZXJlZF9nZW9qc29uIDwtIGdlb2pzb25fZmlsZSB8PiANCiAgZmlsdGVyKG5hbWUgPT0gIlB1ZWJsYSIpDQoNCmdncGxvdCgpICsNCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSBmaWx0ZXJlZF9nZW9qc29uLA0KICAgICAgICAgICAgICAgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwNCiAgICAgICAgICAgICAgIGZpbGwgPSAibGlnaHRncmF5IiwgY29sb3IgPSAid2hpdGUiKSArDQogIGdlb21fcG9pbnQoZGF0YSA9IHJlZF9wb2ludCwgYWVzKHggPSBsb25nLCB5ID0gbGF0KSwgY29sb3IgPSAicmVkIiwgc2l6ZSA9IDMpICsNCiAgdGhlbWVfdm9pZCgpICsNCiAgY29vcmRfbWFwKCkNCmBgYA0KDQojIyMgUG9wdWxhdGlvbiBncmFwaA0KDQpgYGB7cn0NCnB1ZWJfbm9ybQ0KYGBgDQoNCiMjIyBHZXR0aW5nIGNvbHVtbiBuYW1lcw0KDQpgYGB7cn0NCmNvbHVtbl9uYW1lcyA8LSBuYW1lcyhwdWViX25vcm0pDQpjb2x1bW5fbmFtZXMNCmBgYA0KDQojIyMgR2V0dGluZyBjb2x1bW4gbmFtZXMgdGhhdCBoYXZlIHRvIGRvIHdpdGggcG9wdWxhdGlvbiBhZ2UgY29ob3J0cyAoTWFzY3VsaW5lL0ZlbWluaW5lKQ0KDQpgYGB7cn0NCm1hdGNoaW5nX2NvbHVtbnMgPC0gZ3JlcCgiXlBfLipbTUZdJCIsIGNvbHVtbl9uYW1lcywgdmFsdWUgPSBUUlVFKQ0KbWF0Y2hpbmdfY29sdW1ucw0KYGBgDQoNCiMjIyBTZXBhcmF0ZSBieSBzZXgNCg0KYGBge3J9DQplbmRpbmdfaW5fTSA8LSBjaGFyYWN0ZXIoMCkNCmVuZGluZ19pbl9GIDwtIGNoYXJhY3RlcigwKQ0KDQpmb3IgKGNvbF9uYW1lIGluIG1hdGNoaW5nX2NvbHVtbnMpIHsNCiAgaWYgKGVuZHNXaXRoKGNvbF9uYW1lLCAiTSIpKSB7DQogICAgZW5kaW5nX2luX00gPC0gYyhlbmRpbmdfaW5fTSwgY29sX25hbWUpDQogIH0gZWxzZSBpZiAoZW5kc1dpdGgoY29sX25hbWUsICJGIikpIHsNCiAgICBlbmRpbmdfaW5fRiA8LSBjKGVuZGluZ19pbl9GLCBjb2xfbmFtZSkNCiAgfQ0KfQ0KDQpwcmludCgiQ29sdW1uIG5hbWVzIGVuZGluZyBpbiBNOiIpDQpwcmludChlbmRpbmdfaW5fTSkNCg0KcHJpbnQoIkNvbHVtbiBuYW1lcyBlbmRpbmcgaW4gRjoiKQ0KcHJpbnQoZW5kaW5nX2luX0YpDQpgYGANCg0KYGBge3J9DQpjb2hvcnRfbmFtZXNfbSA8LSBjKCJQXzBBNF9NIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfNUE5X00iLA0KICAgICAgICAgICAgICAgICAgICAiUF8xMEExNF9NIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfMTVBMTlfTSIsDQogICAgICAgICAgICAgICAgICAgICJQXzIwQTI0X00iLA0KICAgICAgICAgICAgICAgICAgICAiUF8yNUEyOV9NIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfMzBBMzRfTSIsDQogICAgICAgICAgICAgICAgICAgICJQXzM1QTM5X00iLA0KICAgICAgICAgICAgICAgICAgICAiUF80MEE0NF9NIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfNDVBNDlfTSIsDQogICAgICAgICAgICAgICAgICAgICJQXzUwQTU0X00iLA0KICAgICAgICAgICAgICAgICAgICAiUF81NUE1OV9NIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfNjBBNjRfTSIsDQogICAgICAgICAgICAgICAgICAgICJQXzY1QTY5X00iLA0KICAgICAgICAgICAgICAgICAgICAiUF83MEE3NF9NIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfNzVBNzlfTSIsDQogICAgICAgICAgICAgICAgICAgICJQXzgwQTg0X00iLA0KICAgICAgICAgICAgICAgICAgICAiUF84NVlNQVNfTSIpDQoNCmNvaG9ydF9uYW1lc19mIDwtIGMoIlBfMEE0X0YiLA0KICAgICAgICAgICAgICAgICAgICAiUF81QTlfRiIsDQogICAgICAgICAgICAgICAgICAgICJQXzEwQTE0X0YiLA0KICAgICAgICAgICAgICAgICAgICAiUF8xNUExOV9GIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfMjBBMjRfRiIsDQogICAgICAgICAgICAgICAgICAgICJQXzI1QTI5X0YiLA0KICAgICAgICAgICAgICAgICAgICAiUF8zMEEzNF9GIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfMzVBMzlfRiIsDQogICAgICAgICAgICAgICAgICAgICJQXzQwQTQ0X0YiLA0KICAgICAgICAgICAgICAgICAgICAiUF80NUE0OV9GIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfNTBBNTRfRiIsDQogICAgICAgICAgICAgICAgICAgICJQXzU1QTU5X0YiLA0KICAgICAgICAgICAgICAgICAgICAiUF82MEE2NF9GIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfNjVBNjlfRiIsIA0KICAgICAgICAgICAgICAgICAgICAiUF83MEE3NF9GIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfNzVBNzlfRiIsDQogICAgICAgICAgICAgICAgICAgICJQXzgwQTg0X0YiLCANCiAgICAgICAgICAgICAgICAgICAgIlBfODVZTUFTX0YiKQ0KDQoNCg0KbXVuaWNpcGFsaXR5IDwtICJBY2FqZXRlIg0KbG9jYWxpdHkgPC0gIlNhbiBKYXZpZXIiDQoNCnB1ZWJfbm9ybV9maWx0IDwtIHB1ZWJfbm9ybSB8PiANCiAgICBmaWx0ZXIoTk9NX01VTiA9PSBtdW5pY2lwYWxpdHksIE5PTV9MT0MgPT0gbG9jYWxpdHkpDQoNCmNvaG9ydF9jb3VudHNfbSA8LSBhcy5udW1lcmljKHB1ZWJfbm9ybV9maWx0WzEsY29ob3J0X25hbWVzX21dKQ0KY29ob3J0X2NvdW50c19mIDwtIGFzLm51bWVyaWMocHVlYl9ub3JtX2ZpbHRbMSxjb2hvcnRfbmFtZXNfZl0pDQoNCmRhdGEgPC0gdGliYmxlKA0KICBDb2hvcnQgPSBjKGNvaG9ydF9uYW1lc19tLCBjb2hvcnRfbmFtZXNfZiksDQogIENvdW50ID0gYyhjb2hvcnRfY291bnRzX20sIGNvaG9ydF9jb3VudHNfZiksDQogIFNleCA9IHJlcChjKCJNYWxlIiwgIkZlbWFsZSIpLCBlYWNoID0gbGVuZ3RoKGNvaG9ydF9uYW1lc19tKSkNCikNCg0KIyBQbG90dGluZyBwb3B1bGF0aW9uIHB5cmFtaWQNCmdncGxvdChkYXRhLCBhZXMoeCA9IHJlb3JkZXIoQ29ob3J0LCAtQ291bnQpLCB5ID0gQ291bnQsIGZpbGwgPSBTZXgpKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJpZGVudGl0eSIpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiYmx1ZSIsICJwaW5rIikpICsgIA0KICBjb29yZF9mbGlwKCkgKyAgDQogIGxhYnModGl0bGUgPSAiUG9wdWxhdGlvbiBQeXJhbWlkIiwNCiAgICAgICB4ID0gIlBvcHVsYXRpb24gQ291bnQiLA0KICAgICAgIHkgPSAiQWdlIENvaG9ydCIsDQogICAgICAgZmlsbCA9ICJTZXgiKSArDQogIHRoZW1lX21pbmltYWwoKSAgDQoNCmBgYA0KDQpgYGB7cn0NCm5ld19hZ2VzIDwtIGMoIjAtNCIsDQogICAgICAgICAgICAgICAgICI1LTkiLA0KICAgICAgICAgICAgICAgICAiMTAtMTQiLA0KICAgICAgICAgICAgICAgICAiMTUtMTkiLA0KICAgICAgICAgICAgICAgICAiMjAtMjQiLA0KICAgICAgICAgICAgICAgICAiMjUtMjkiLCANCiAgICAgICAgICAgICAgICAgIjMwLTM0IiwgDQogICAgICAgICAgICAgICAgICIzNS0zOSIsIA0KICAgICAgICAgICAgICAgICAiNDAtNDQiLCANCiAgICAgICAgICAgICAgICAgIjQ1LTQ5IiwNCiAgICAgICAgICAgICAgICAgIjUwLTU0IiwNCiAgICAgICAgICAgICAgICAgIjU1LTU5IiwNCiAgICAgICAgICAgICAgICAgIjYwLTY0IiwgDQogICAgICAgICAgICAgICAgICI2NS02OSIsDQogICAgICAgICAgICAgICAgICI3MC03NCIsIA0KICAgICAgICAgICAgICAgICAiNzUtNzkiLCANCiAgICAgICAgICAgICAgICAgIjgwLTg0IiwgDQogICAgICAgICAgICAgICAgICI4NSsiKQ0KDQpkYXRhIDwtIHRpYmJsZSgNCiAgQWdlID0gcGFzdGUwKG5ld19hZ2VzKSwNCiAgTWFsZSA9IHNhbXBsZSgyMDA6MTAwMCwgbGVuZ3RoKGNvaG9ydF9uYW1lc19tKSwgcmVwbGFjZSA9IFRSVUUpLA0KICBGZW1hbGUgPSBzYW1wbGUoMjAwOjEwMDAsIGxlbmd0aChjb2hvcnRfbmFtZXNfZiksIHJlcGxhY2UgPSBUUlVFKQ0KKQ0KDQpkYXRhX2xvbmcgPC0gcGl2b3RfbG9uZ2VyKA0KICBkYXRhLCANCiAgY29scyA9IGMoTWFsZSwgRmVtYWxlKSwgDQogIG5hbWVzX3RvID0gIlNleCIsIA0KICB2YWx1ZXNfdG8gPSAiUG9wdWxhdGlvbiINCikNCg0KYmFzaWNfcGxvdCA8LSBnZ3Bsb3QoZGF0YV9sb25nLCBhZXMoeCA9IEFnZSwgeSA9IGlmZWxzZShTZXggPT0gIk1hbGUiLCAtUG9wdWxhdGlvbiwgUG9wdWxhdGlvbiksIGZpbGwgPSBTZXgpKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBhYnMsIGxpbWl0cyA9IG1heChkYXRhX2xvbmckUG9wdWxhdGlvbikgKiBjKC0xLCAxKSkgKw0KICBjb29yZF9mbGlwKCkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICBsYWJzKHggPSAiQWdlIiwgeSA9ICJQb3B1bGF0aW9uIiwgZmlsbCA9ICJTZXgiLCB0aXRsZSA9ICJQb3B1bGF0aW9uIFB5cmFtaWQiKQ0KDQpiYXNpY19wbG90DQpgYGANCg0KIyMjIENvbXBsZXRlIHBpcGVsaW5lDQoNCmBgYHtyfQ0KY2Vuc3VzX2RhdGFzZXQgPC0gb3Blbl9kYXRhc2V0KGhlcmUoImRhdGEiLCAicHJvY2Vzc2VkIiwgInBhcnF1ZXRfZGF0YV9jb29yZHMiKSkNCg0KDQpwdWViX25vcm0gPC0gY2Vuc3VzX2RhdGFzZXQgfD4NCiAgICBmaWx0ZXIoTk9NX0VOVD09IlB1ZWJsYSIpIHw+IA0KICAgIGNvbGxlY3QoKQ0KDQptdW5pY2lwYWxpdHkgPC0gIkFjYWpldGUiDQpsb2NhbGl0eSA8LSAiU2FuIEphdmllciINCg0KcHVlYl9ub3JtX2ZpbHQgPC0gcHVlYl9ub3JtIHw+IA0KICAgIGZpbHRlcihOT01fTVVOID09IG11bmljaXBhbGl0eSwgTk9NX0xPQyA9PSBsb2NhbGl0eSkNCg0KDQpjb2hvcnRfbmFtZXNfbSA8LSBjKCJQXzBBNF9NIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfNUE5X00iLA0KICAgICAgICAgICAgICAgICAgICAiUF8xMEExNF9NIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfMTVBMTlfTSIsDQogICAgICAgICAgICAgICAgICAgICJQXzIwQTI0X00iLA0KICAgICAgICAgICAgICAgICAgICAiUF8yNUEyOV9NIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfMzBBMzRfTSIsDQogICAgICAgICAgICAgICAgICAgICJQXzM1QTM5X00iLA0KICAgICAgICAgICAgICAgICAgICAiUF80MEE0NF9NIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfNDVBNDlfTSIsDQogICAgICAgICAgICAgICAgICAgICJQXzUwQTU0X00iLA0KICAgICAgICAgICAgICAgICAgICAiUF81NUE1OV9NIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfNjBBNjRfTSIsDQogICAgICAgICAgICAgICAgICAgICJQXzY1QTY5X00iLA0KICAgICAgICAgICAgICAgICAgICAiUF83MEE3NF9NIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfNzVBNzlfTSIsDQogICAgICAgICAgICAgICAgICAgICJQXzgwQTg0X00iLA0KICAgICAgICAgICAgICAgICAgICAiUF84NVlNQVNfTSIpDQoNCmNvaG9ydF9uYW1lc19mIDwtIGMoIlBfMEE0X0YiLA0KICAgICAgICAgICAgICAgICAgICAiUF81QTlfRiIsDQogICAgICAgICAgICAgICAgICAgICJQXzEwQTE0X0YiLA0KICAgICAgICAgICAgICAgICAgICAiUF8xNUExOV9GIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfMjBBMjRfRiIsDQogICAgICAgICAgICAgICAgICAgICJQXzI1QTI5X0YiLA0KICAgICAgICAgICAgICAgICAgICAiUF8zMEEzNF9GIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfMzVBMzlfRiIsDQogICAgICAgICAgICAgICAgICAgICJQXzQwQTQ0X0YiLA0KICAgICAgICAgICAgICAgICAgICAiUF80NUE0OV9GIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfNTBBNTRfRiIsDQogICAgICAgICAgICAgICAgICAgICJQXzU1QTU5X0YiLA0KICAgICAgICAgICAgICAgICAgICAiUF82MEE2NF9GIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfNjVBNjlfRiIsIA0KICAgICAgICAgICAgICAgICAgICAiUF83MEE3NF9GIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfNzVBNzlfRiIsDQogICAgICAgICAgICAgICAgICAgICJQXzgwQTg0X0YiLCANCiAgICAgICAgICAgICAgICAgICAgIlBfODVZTUFTX0YiKQ0KDQoNCg0KbmV3X2FnZXMgPC0gYygiMC00IiwNCiAgICAgICAgICAgICAgICAgIjUtOSIsDQogICAgICAgICAgICAgICAgICIxMC0xNCIsDQogICAgICAgICAgICAgICAgICIxNS0xOSIsDQogICAgICAgICAgICAgICAgICIyMC0yNCIsDQogICAgICAgICAgICAgICAgICIyNS0yOSIsIA0KICAgICAgICAgICAgICAgICAiMzAtMzQiLCANCiAgICAgICAgICAgICAgICAgIjM1LTM5IiwgDQogICAgICAgICAgICAgICAgICI0MC00NCIsIA0KICAgICAgICAgICAgICAgICAiNDUtNDkiLA0KICAgICAgICAgICAgICAgICAiNTAtNTQiLA0KICAgICAgICAgICAgICAgICAiNTUtNTkiLA0KICAgICAgICAgICAgICAgICAiNjAtNjQiLCANCiAgICAgICAgICAgICAgICAgIjY1LTY5IiwNCiAgICAgICAgICAgICAgICAgIjcwLTc0IiwgDQogICAgICAgICAgICAgICAgICI3NS03OSIsIA0KICAgICAgICAgICAgICAgICAiODAtODQiLCANCiAgICAgICAgICAgICAgICAgIjg1KyIpDQoNCg0KZGF0YSA8LSB0aWJibGUoDQogIEFnZSA9IHBhc3RlMChuZXdfYWdlcyksDQogIE1hbGUgPSBhcy5udW1lcmljKHB1ZWJfbm9ybV9maWx0WzEsY29ob3J0X25hbWVzX21dKSwNCiAgRmVtYWxlID0gYXMubnVtZXJpYyhwdWViX25vcm1fZmlsdFsxLGNvaG9ydF9uYW1lc19mXSkNCikNCg0KZGF0YV9sb25nIDwtIHBpdm90X2xvbmdlcigNCiAgZGF0YSwgDQogIGNvbHMgPSBjKE1hbGUsIEZlbWFsZSksIA0KICBuYW1lc190byA9ICJTZXgiLCANCiAgdmFsdWVzX3RvID0gIlBvcHVsYXRpb24iDQopDQpiYXNpY19wbG90IDwtIGdncGxvdChkYXRhX2xvbmcsIGFlcyh4ID0gQWdlLCB5ID0gaWZlbHNlKFNleCA9PSAiTWFsZSIsIC1Qb3B1bGF0aW9uLCBQb3B1bGF0aW9uKSwgZmlsbCA9IFNleCkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGFicywgbGltaXRzID0gbWF4KGRhdGFfbG9uZyRQb3B1bGF0aW9uKSAqIGMoLTEsIDEpKSArDQogIGNvb3JkX2ZsaXAoKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnMoeCA9ICJBZ2UiLCB5ID0gIlBvcHVsYXRpb24iLCBmaWxsID0gIlNleCIsIHRpdGxlID0gIlBvcHVsYXRpb24gUHlyYW1pZCIpDQoNCmJhc2ljX3Bsb3QNCmBgYA0KDQojIyMgQ2FyZA0KDQpgYGB7cn0NCiMgY2FyZCA8LSBjZW5zdXNfZGF0YXNldCB8PiAgDQojICAgICBmaWx0ZXIoDQojICAgICAgIE5PTV9FTlQgPT0gIlB1ZWJsYSIsDQojICAgICAgIE5PTV9NVU4gPT0gIkFjYXRlbm8iLA0KIyAgICAgICBOT01fTE9DID09ICJTYW50YSBBbmRyZWEiDQojICAgICApIHw+IA0KIyAgIGNvbGxlY3QoKQ0KICAgIA0KICAgIHRvdGFsX3BvcHVsYXRpb24gPC0gYXMubnVtZXJpYyhjYXJkWzEsIGMoIlBPQlRPVCIpXSwgbmEucm0gPSBUUlVFKQ0KICAgIHBhc3RlKCJUb3RhbCBQb3B1bGF0aW9uOiIsIHRvdGFsX3BvcHVsYXRpb24pDQpgYGANCg0KIyMjIFBpZQ0KDQpgYGB7cn0NCnRvdCA8LSBjZW5zdXNfZGF0YXNldCB8Pg0KICAgIGZpbHRlcihOT01fRU5UPT0iVG90YWwgbmFjaW9uYWwiKSB8PiANCiAgICBjb2xsZWN0KCkNCg0KdG90DQpgYGANCg0KYGBge3J9DQojIG9yaWdpbiA8LSBjZW5zdXNfZGF0YXNldCB8PiAgDQojICAgICAgZmlsdGVyKA0KIyAgICAgICBOT01fRU5UID09ICJQdWVibGEiLA0KIyAgICAgICBOT01fTVVOID09ICJBY2F0ZW5vIiwNCiMgICAgICAgTk9NX0xPQyA9PSAiU2FudGEgQW5kcmVhIg0KIyAgICAgKSB8Pg0KIyAgIGNvbGxlY3QoKQ0KICAgIA0KdG90DQogICAgDQogICAgIyBFeHRyYWN0IGJpcnRoIGRhdGENCiAgICBiaXJ0aF9sb2NhbCA8LSBhcy5udW1lcmljKHRvdFsxLCAiUE5BQ0VOVCJdKQ0KICAgIGJpcnRoX2Fub3RoZXIgPC0gYXMubnVtZXJpYyh0b3RbMSwgIlBOQUNPRSJdKQ0KICAgIA0KICAgICMgRGVidWdnaW5nIG91dHB1dA0KICAgIHByaW50KHBhc3RlKCJCaXJ0aCBMb2NhbDoiLCBiaXJ0aF9sb2NhbCkpDQogICAgcHJpbnQocGFzdGUoIkJpcnRoIEFub3RoZXI6IiwgYmlydGhfYW5vdGhlcikpDQogICAgDQogICAgIyBDcmVhdGUgcmF0aW8gZGF0YWZyYW1lDQogICAgcmF0aW9fZGYgPC0gdGliYmxlKA0KICAgICAgQ2F0ZWdvcnkgPSBjKCJMb2NhbCIsICJPdGhlciIpLA0KICAgICAgUmF0aW8gPSBjKGJpcnRoX2xvY2FsLCBiaXJ0aF9hbm90aGVyKQ0KICAgICkNCiAgICANCiAgICAjIENhbGN1bGF0ZSBwZXJjZW50YWdlcw0KICAgIHJhdGlvX2RmJFBlcmNlbnRhZ2UgPC0gcmF0aW9fZGYkUmF0aW8gLyBzdW0ocmF0aW9fZGYkUmF0aW8pICogMTAwDQogICAgDQogICAgIyBQbG90IHRoZSBwaWUgY2hhcnQNCiAgICBnZyA8LSBnZ3Bsb3QocmF0aW9fZGYsIGFlcyh4ID0gIiIsIHkgPSBSYXRpbywgZmlsbCA9IENhdGVnb3J5KSkgKw0KICAgICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHdpZHRoID0gMSkgKw0KICAgICAgY29vcmRfcG9sYXIodGhldGEgPSAieSIpICsNCiAgICAgIHRoZW1lX3ZvaWQoKSArDQogICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgKw0KICAgICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzAwQkZDNCIsICIjRjg3NjZEIikpICsNCiAgICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBwYXN0ZTAocm91bmQoUGVyY2VudGFnZSksICIlIikpLCANCiAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gMC41KSwNCiAgICAgICAgICAgICAgICBzaXplID0gNSwgY29sb3IgPSAid2hpdGUiLCBmb250ZmFjZSA9ICJib2xkIikNCiAgICANCiAgICBnZw0KICAgIA0KYGBgDQo=